﻿using Ninject;
using NUnit.Framework;
using Nx.Bootstrappers;
using Nx.Clients.Tests;
using Nx.Extensions;
using Nx.Logging;
using System.Web.Http;
using System.Web.Http.Dependencies;
using System.Web.Http.SelfHost;

/// <summary>
/// The Assembly setup is intentionally in global namespace. This will be run prior to ALL test fixtures in the assembly.
/// http://www.ncrunch.net/documentation/considerations-and-constraints_test-atomicity
/// </summary>
[SetUpFixture]
public class AssemblySetup
{
    public static int _InitializationCount = 0;
    public static bool _AssemblyInitialized = false;
    private static object _lock = new object();

    private static HttpSelfHostServer Server;
    private static HttpSelfHostConfiguration Configuration;
    protected static string BaseAddress = "http://localhost:8080";

    public static IKernel Kernel { get; private set; }
    private ILogger _Logger;

    [SetUp]
    public async void SetUp()
    {
        if (!_AssemblyInitialized)
        {
            lock (_lock)
            {
                if (!_AssemblyInitialized)
                {
                    using (IBootstrapper bootstrapper = new Bootstrapper()
                                .ExtendBy<NxLoggingExtension>()
                                .ExtendBy<NxWebExtension>())
                    {
                        Kernel = bootstrapper.Run();
                        _InitializationCount++;
                        _Logger = Kernel.Get<ILogFactory>().CreateLogger("AssemblySetup");
                        _Logger.Info("Test assembly has been set up");
                    }

                    Configuration = new HttpSelfHostConfiguration(BaseAddress);
                    Configuration.Routes.MapHttpRoute(name: "DefaultApi",
                        routeTemplate: "api/{controller}/{action}/{id}",
                        defaults: new
                        {
                            action = RouteParameter.Optional,
                            id = RouteParameter.Optional
                        });

                    Configuration.DependencyResolver = Kernel.Get<IDependencyResolver>();

                    Server = new HttpSelfHostServer(Configuration);
                    Server.OpenAsync().Wait();

                    _AssemblyInitialized = true;
                }
            }
        }
    }

    [TearDown]
    public void TearDown()
    {
        if (_AssemblyInitialized)
        {
            lock (_lock)
            {
                if (_AssemblyInitialized)
                {
                    if (Kernel != null)
                    {
                        _Logger.Info("Test assembly is being torn down");
                        Kernel.Dispose();
                        _Logger.Dispose();
                    }

                    if (Server != null)
                    {
                        Server.CloseAsync().Wait();
                        Server.Dispose();
                    }

                    _AssemblyInitialized = false;
                }
            }
        }
    }
}
